package com.jeecg.demo.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.jeecgframework.core.common.model.json.DataGrid;
import org.jeecgframework.core.online.def.CgReportConstant;
import org.jeecgframework.core.online.exception.CgReportNotFoundException;
import org.jeecgframework.core.util.StringUtil;
import org.jeecgframework.p3.core.utils.common.StringUtils;
import org.jeecgframework.web.cgform.common.CgAutoListConstant;
import org.jeecgframework.web.cgform.entity.config.CgFormFieldEntity;
import org.jeecgframework.web.cgform.service.autolist.ConfigServiceI;
import org.jeecgframework.web.cgform.service.config.CgFormFieldServiceI;
import org.jeecgframework.web.cgreport.service.core.CgReportServiceI;
import org.jeecgframework.web.system.service.SystemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * Popup列内容数据绑定助手
 */
@Component
public class PopupDataBindUtil {
    @Autowired
    private SystemService systemService;
    @Autowired
    private ConfigServiceI configService;
    @Autowired
    private CgFormFieldServiceI cgFormFieldService;
    @Autowired
    private CgReportServiceI cgReportService;

    /**
     * 根据参数绑定数据表数据 例: bindUtil.BindDDName(dataGrid, "trader", "fullname",
     * "traderid", "orgid", "orgidname");
     * 搜索名字叫Trader表下的fullname字段，条件是表的traderid等于数据对象的orgid值， 最后绑定到数据的列名为orgidname
     * 
     * @param dataGrid
     *            数据对象
     * @param tableName
     *            数据表名称
     * @param fieldName
     *            数据表字段
     * @param queryName
     *            数据表查询条件字段
     * @param keyName
     *            要绑定的数据对象字段名称
     * @param bindName
     *            绑定到数据对象的字段名称
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public void BindDDName(DataGrid dataGrid, String tableName,
            String fieldName, String queryName, String keyName, String bindName)
            throws Exception {
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();

        boolean isMap = false;

        if (dataGrid.getResults().size() > 0
                && "java.util.HashMap".equals(dataGrid.getResults().get(0)
                        .getClass().getName())) {
            isMap = true;
        }

        for (Object item : dataGrid.getResults()) {
            Map<String, Object> itemMap = null;

            if (isMap) {
                itemMap = (Map<String, Object>) item;
            }
            else {
                itemMap = objectToMap(item);
            }

            if (itemMap != null) {

                if (itemMap.get(keyName) != null) {
                    List<String> results = systemService
                            .findListbySql("select " + fieldName + " from "
                                    + tableName + " where " + queryName
                                    + " in (" + itemMap.get(keyName).toString()
                                    + ")");

                    if (results != null && !results.toString().equals("")) {
                        itemMap.put(bindName, results.toString().replace("[",
                                "").replace("]", ""));
                    }
                    else {
                        itemMap.put(bindName, "");
                    }
                }

                resultList.add(itemMap);
            }
        }

        dataGrid.setResults(resultList);
    }

    /**
     * 绑定报表对应字段名称
     * 
     * @param dataGrid
     *            数据表
     * @param keyName
     *            要绑定的数据对象字段名称
     * @param queryFieldName
     *            要查询的数据表字段
     * @return
     * @throws Exception
     */
    public void BindReportFieldNameDataGrid(Class<?> entityClass,
            DataGrid dataGrid, String keyName, String fieldName)
            throws Exception {
        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
        List<CgFormFieldEntity> beans = new ArrayList<CgFormFieldEntity>();
        String configId = "";

        Annotation[] annotations = entityClass.getAnnotations();

        for (Annotation item : annotations) {
            if (item instanceof javax.persistence.Table) {
                configId = ((javax.persistence.Table) item).name();
                beans = getReportFieldEntity(configId);
            }
        }

        for (Object item : dataGrid.getResults()) {
            Map<String, Object> itemMap = BindReportFieldName(item, configId,
                    keyName, fieldName, beans);
            resultList.add(itemMap);
        }

        if (resultList.size() > 0) {
            dataGrid.setResults(resultList);
        }
    }

    /**
     * 绑定报表对应字段名称
     * 
     * @param task
     *            数据对象
     * @param keyName
     *            要绑定的数据对象字段名称
     * @param queryFieldName
     *            要查询的数据表字段
     * @return
     * @throws Exception
     */
    public Map<String, Object> BindReportFieldName(Class<?> entityClass,
            Object task, String keyName, String fieldName) throws Exception {
        List<CgFormFieldEntity> beans = new ArrayList<CgFormFieldEntity>();
        Annotation[] annotations = entityClass.getAnnotations();
        String configId = "";

        for (Annotation item : annotations) {
            if (item instanceof javax.persistence.Table) {
                configId = ((javax.persistence.Table) item).name();
                beans = getReportFieldEntity(configId);
            }
        }

        return BindReportFieldName(task, configId, keyName, fieldName, beans);
    }

    /**
     * 绑定报表对应字段名称
     * 
     * @param task
     *            数据对象
     * @param configId
     *            配置信息ID
     * @param keyName
     *            要绑定的数据对象字段名称
     * @param queryFieldName
     *            要查询的数据表字段
     * @return
     * @throws Exception
     */
    public Map<String, Object> BindReportFieldName(Object task,
            String configId, String keyName, String fieldName) throws Exception {
        return BindReportFieldName(task, configId, keyName, fieldName, null);
    }

    /**
     * 绑定报表对应字段名称
     * 
     * @param task
     *            数据对象
     * @param configId
     *            配置信息ID
     * @param keyName
     *            要绑定的数据对象字段名称
     * @param queryFieldName
     *            要查询的数据表字段
     * @param beans
     *            配置对象
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> BindReportFieldName(Object task,
            String configId, String keyName, String queryFieldName,
            List<CgFormFieldEntity> beans) throws Exception {
        Map<String, Object> result;

        if (null != task
                && !"java.util.HashMap".equals(task.getClass().getName())) {
            result = objectToMap(task);
        }
        else {
            result = (Map<String, Object>) task;
        }

        if (beans == null) {
            beans = getReportFieldEntity(configId);
        }

        for (CgFormFieldEntity item : beans) {
            String fieldName = convertDatabaseFieldNameToMapFieldName(item
                    .getFieldName());

            if (fieldName.equals(keyName)) {
                if (result.get(fieldName) != null) {
                    if (!StringUtil.isEmpty(item.getDictTable())) {
                        Map<String, Object> cgReportMap = null;
                        try {
                            cgReportMap = cgReportService
                                    .queryCgReportConfig(item.getDictTable());
                            if (cgReportMap.size() <= 0) {
                                throw new CgReportNotFoundException(
                                        "动态报表配置不存在!");
                            }
                        }
                        catch (Exception e) {
                            throw new CgReportNotFoundException("查找动态报表配置失败!"
                                    + e.getMessage());
                        }

                        Map configM = (Map) cgReportMap
                                .get(CgReportConstant.MAIN);
                        String querySql = (String) configM
                                .get(CgReportConstant.CONFIG_SQL);
                        Map<String, Object> pageSearchFields = new LinkedHashMap<String, Object>();

                        if (querySql.indexOf("where") > 0) {
                            querySql += " and ";
                        }
                        else {
                            querySql += " where ";
                        }

                        if (item.getType().equals("string")) {
                            querySql += item.getDictText() + " in ("
                                    + result.get(fieldName).toString() + ")";
                        }
                        else {
                            querySql += item.getDictText() + " in ("
                                    + result.get(fieldName).toString() + ")";
                        }

                        List<Map<String, Object>> resultsss = cgReportService
                                .queryByCgReportSql(querySql, pageSearchFields,
                                        new HashMap<String, Object>(), -1, -1);

                        String dicName = "";

                        for (Map<String, Object> itemR : resultsss) {
                            dicName += ","
                                    + itemR.get(queryFieldName).toString();
                        }

                        if (!StringUtils.isEmpty(dicName)) {
                            dicName = dicName.substring(1);
                            result.put(fieldName + "DicName", dicName);
                        }
                        else {
                            result.put(fieldName + "DicName", "");
                        }
                    }
                }
            }
        }
        return result;
    }

    public Map<String, Object> BindDDName(Object obj, String tableName,
            String fieldName, String queryName, String keyName, String bindName)
            throws Exception {
        Map<String, Object> itemc = objectToMap(obj);

        if (keyName != null) {
            List<String> aaa = systemService.findListbySql("select "
                    + fieldName + " from " + tableName + " where " + queryName
                    + " in (" + itemc.get(keyName).toString() + ")");

            if (aaa != null) {
                itemc.put(bindName, aaa.toString().replace("[", "").replace(
                        "]", ""));
            }
        }

        return itemc;

    }

    /**
     * 查询有关联报表字段信息
     * 
     * @param configId
     * @return
     */
    private List<CgFormFieldEntity> getReportFieldEntity(String configId) {
        List<CgFormFieldEntity> beans = getCgFormFieldEntity(configId);
        List<CgFormFieldEntity> beansFilter = new ArrayList<CgFormFieldEntity>();

        // 只添加有关联报表的字段信息
        for (CgFormFieldEntity item : beans) {
            if (item.getShowType().equals("popup")) {
                if (!StringUtil.isEmpty(item.getDictField())) {
                    beansFilter.add(item);
                }
            }
        }
        return beansFilter;
    }

    /**
     * 查询字段信息
     * 
     * @param configId
     * @return
     */
    @SuppressWarnings("unchecked")
    private List<CgFormFieldEntity> getCgFormFieldEntity(String configId) {
        String jversion = cgFormFieldService
                .getCgFormVersionByTableName(configId);
        Map<String, Object> configs = configService.queryConfigs(configId,
                jversion);
        List<CgFormFieldEntity> beans = (List<CgFormFieldEntity>) configs
                .get(CgAutoListConstant.FILEDS);

        return beans;
    }

    /**
     * 将数据库字段名称转换为Map字段名称
     * 
     * @param baseFieldName
     * @return
     */
    private String convertDatabaseFieldNameToMapFieldName(String baseFieldName) {
        String fieldName = baseFieldName;

        while (fieldName.indexOf("_") > 0) {
            int findex = fieldName.indexOf("_");

            if (findex < fieldName.length() - 1) {
                fieldName = fieldName.substring(0, findex)
                        + fieldName.substring(findex + 1, findex + 2)
                                .toUpperCase()
                        + fieldName.substring(findex + 2);
            }
            else {
                break;
            }
        }

        return fieldName;
    }

    /**
     * 将数据对象转换为Map
     * 
     * @param obj
     *            数据对象
     * @return
     * @throws Exception
     */
    private Map<String, Object> objectToMap(Object obj) throws Exception {
        if (obj == null)
            return null;

        Map<String, Object> map = new HashMap<String, Object>();

        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo
                .getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter != null ? getter.invoke(obj) : null;
            map.put(key, value);
        }

        return map;
    }

    /**
     * 将ids字符串转换为Integer数组用于查询
     * 
     * @param ids
     * @return
     */
    public Integer[] idsToIntegerArray(String ids) {

        if (ids == null) {
            return null;
        }

        List<Integer> listIds = new ArrayList<Integer>();
        String[] idsArray = ids.split(",");
        for (String item : idsArray) {
            if (null != item && !"".equals(item)) {
                listIds.add(Integer.valueOf(item));
            }
        }

        return listIds.toArray(new Integer[listIds.size()]);
    }
}
